''' <summary>
''' Rather than inheriting from IniFile, use this to constantly open and close the ini file; it is slower but assures that WRDBProject doesn't step on toes
''' Procedure: at any time can call any routine and inifile will automatically be opened; after batch of routines are done, must execute Close method
''' </summary>
Public Class clsWRDBIniFile

    Private _ProjectName As String
    Private _IniFileName As String
    Private _IniFile As WRDB.IniFile.clsIniFile

    ''' <summary>
    ''' Application settings will go under the Settings section
    ''' Project settings will go under a section with the same name as the project
    ''' External Connection settings will go under the ExternalConnections section; 
    '''    each key will be the name of the connection and all settings will be 
    '''    concatenated on the same line
    ''' </summary>
    Public Enum enumSection
        Application
        Project
        ExternalConnection
    End Enum

    ''' <summary>
    ''' Standard application and project keys which are mapped to the actual key names; this allows use of Intellisense to ensure that the correct key names are used
    ''' </summary>
    Public Enum enumKey
        'begin keys global to the application (for this user)
        AppLastProjectName
        AppLastQueryProject
        AppLastQueryTable
        AppLastQueryTime
        AppLastQuerySQL
        AppLastQueryRecords
        AppLastEditTime
        AppExpertMode
        AppShowStartup
        AppShowNewProject
        AppShowGettingStarted
        AppCheckUpdates
        AppUpdateLocation
        AppProxyAddress
        AppProxyUsername
        AppProxyPassword
        AppRptHeading1
        AppRptHeading2
        AppRptScaling
        AppRptLanguage
        AppPromptImport
        AppUserName
        AppPrintMarginsLeft
        AppPrintMarginsRight
        AppPrintMarginsTop
        AppPrintMarginsBottom
        AppGridFontName
        AppGridFontSize
        AppSQLServerURL
        AppSQLUserName
        AppSQLPassword
        AppSQLReportPath
        AppSQLTimeout
        AppSQLReports

        'begin keys for each project
        Description
        Password
        TitleBarText
        DesktopGraphic
        DesktopColorTheme
        MasterTable
        Path_Master
        Path_Support
        Path_SupportProj
        Path_Working
        Path_Archive
        Path_BulkInsert
        Path_SQL
        DatabaseType
        DataSource
        DatabaseName
        DbUserName
        DbPassword
        ExportPath
        ExportFormat
        Rpt_OutputTo
        Rpt_Comments
        Rpt_DateTimeRCode
        Rpt_DateTimeDate
        ShowTablesOnly
        Timeout
        DisplayRecordCount
        QueryOption
        AdvancedMenus
        IsReadOnly
        WQXVisible
        GisQuickList
        GisQuickTable
        GisDirectory

        NumGIS
        GIS_XMin
        GIS_XMax
        GIS_YMin
        GIS_YMax
        GIS_Display
        GIS_PCode
        GIS_Aggregate
        GIS_DateTime
        GIS_AnimSpeed
        GIS_DataFile
        GIS_DataFileRelative
        GIS_DataLayer
        GIS_DataField
        GIS_DataColor0
        GIS_DataColor1
        GIS_DataColor2
        GIS_DataColor3
        GIS_DataColor4
        GIS_DataInvert
        GIS_DataThresholdType
        GIS_DataThresholdValue

        GISName
        GISShapeFile
        GISShapeFileRelative
        GISLineColor
        GISLineWidth
        GISLineStipple
        GISFilled
        GISFillColor
        GISFillStipple
        GISFillTransparency
        GISVisible
        GISPointColor
        GISPointSize
        GISPointType

    End Enum

    Public ReadOnly Property FileName() As String
        Get
            Return _IniFileName
        End Get
    End Property

    ''' <summary>
    ''' Get the desired Ini file section name depending is the setting is global for the application or specific to the project
    ''' </summary>
    ''' <param name="SectionType">Application or Project type</param>
    ''' <returns>Name of section to use in Ini file</returns>
    Private Function SectionName(ByVal SectionType As enumSection) As String
        Select Case SectionType
            Case enumSection.Application : Return "Settings"
            Case enumSection.Project : Return _ProjectName
            Case enumSection.ExternalConnection : Return "ExternalConnections"
            Case Else
                Debug.Assert(False, "Invalid section passed to SectionName")
                Return "Unknown"
        End Select
    End Function

    ''' <summary>
    ''' Get the desired Ini file key name
    ''' </summary>
    ''' <param name="KeyType">One of the standard enumerated key types</param>
    ''' <returns>Name of key to use in Ini file</returns>
    Private Function KeyName(ByVal KeyType As enumKey) As String
        Select Case KeyType
            Case enumKey.AppLastProjectName : Return "LastProject"
            Case enumKey.AppLastQueryProject : Return "Query Project"
            Case enumKey.AppLastQueryTable : Return "Query Table"
            Case enumKey.AppLastQueryTime : Return "Query Time"
            Case enumKey.AppLastQuerySQL : Return "Query SQL"
            Case enumKey.AppLastQueryRecords : Return "Query Records"
            Case enumKey.AppExpertMode : Return "Expert"
            Case enumKey.AppPromptImport : Return "Prompt Import"
            Case enumKey.AppRptHeading1 : Return "Report Heading 1"
            Case enumKey.AppRptHeading2 : Return "Report Heading 2"
            Case enumKey.AppRptScaling : Return "Report Scaling"
            Case enumKey.AppRptLanguage : Return "Report Language"
            Case enumKey.AppShowStartup : Return "Show Startup"
            Case enumKey.AppShowNewProject : Return "Show New Project"
            Case enumKey.AppShowGettingStarted : Return "Show Getting Started"
            Case enumKey.AppCheckUpdates : Return "Check Updates"
            Case enumKey.AppUpdateLocation : Return "Update Location"
            Case enumKey.AppProxyAddress : Return "Proxy Address"
            Case enumKey.AppProxyUsername : Return "Proxy UserName"
            Case enumKey.AppProxyPassword : Return "Proxy Password"
            Case enumKey.AppUserName : Return "User Name"
            Case enumKey.AppLastEditTime : Return "Last Edit Time"
            Case enumKey.AppPrintMarginsLeft : Return "Print Margins Left"
            Case enumKey.AppPrintMarginsRight : Return "Print Margins Right"
            Case enumKey.AppPrintMarginsTop : Return "Print Margins Top"
            Case enumKey.AppPrintMarginsBottom : Return "Print Margins Bottom"
            Case enumKey.AppGridFontName : Return "Grid Font Name"
            Case enumKey.AppGridFontSize : Return "Grid Font Size"
            Case enumKey.AppSQLServerURL : Return "SQL Server URL"
            Case enumKey.AppSQLUserName : Return "SQL User Name"
            Case enumKey.AppSQLPassword : Return "SQL Password"
            Case enumKey.AppSQLReportPath : Return "SQL Report Path"
            Case enumKey.AppSQLTimeout : Return "SQL Timeout"
            Case enumKey.AppSQLReports : Return "SQL Reports"

            Case enumKey.Description : Return "ProjectDesc"
            Case enumKey.Password : Return "Password"
            Case enumKey.TitleBarText : Return "TitleBarText"
            Case enumKey.DesktopGraphic : Return "DesktopGraphic"
            Case enumKey.DesktopColorTheme : Return "DesktopColorTheme"
            Case enumKey.MasterTable : Return "MasterDB"
            Case enumKey.Path_Master : Return "MasterPath"
            Case enumKey.Path_Support : Return "SupportPath"
            Case enumKey.Path_SupportProj : Return "ProjectSupportPath"
            Case enumKey.Path_Working : Return "TempPath"
            Case enumKey.Path_Archive : Return "SupportArchivePath"
            Case enumKey.Path_BulkInsert : Return "BulkInsertDir"
            Case enumKey.Path_SQL : Return "SQLDir"
            Case enumKey.DatabaseType : Return "DatabaseType"
            Case enumKey.DataSource : Return "DataSource"
            Case enumKey.DatabaseName : Return "DatabaseName"
            Case enumKey.DbUserName : Return "DbUserName"
            Case enumKey.DbPassword : Return "DbPassword"
            Case enumKey.Timeout : Return "Timeout"
            Case enumKey.DisplayRecordCount : Return "DisplayRecordCount"
            Case enumKey.QueryOption : Return "QueryOption"
            Case enumKey.AdvancedMenus : Return "AdvancedMenus"
            Case enumKey.IsReadOnly : Return "IsReadOnly"
            Case enumKey.WQXVisible : Return "WQXVisible"

            Case enumKey.ExportPath : Return "ExportPath"
            Case enumKey.ExportFormat : Return "ExportFormat"

            Case enumKey.AppRptHeading1 : Return "Heading1"
            Case enumKey.AppRptHeading2 : Return "Heading2"
            Case enumKey.Rpt_OutputTo : Return "OutputTo"
            Case enumKey.Rpt_Comments : Return "RptComments"
            Case enumKey.ShowTablesOnly : Return "ShowTablesOnly"

            Case enumKey.NumGIS : Return "NumGIS"
            Case enumKey.GIS_XMin : Return "GIS_XMin"
            Case enumKey.GIS_XMax : Return "GIS_XMax"
            Case enumKey.GIS_YMin : Return "GIS_YMin"
            Case enumKey.GIS_YMax : Return "GIS_YMax"
            Case enumKey.GIS_Aggregate : Return "GIS_Aggregate"
            Case enumKey.GIS_AnimSpeed : Return "GIS_AnimSpeed"
            Case enumKey.GIS_DateTime : Return "GIS_DateTime"
            Case enumKey.GIS_Display : Return "GIS_Display"
            Case enumKey.GIS_PCode : Return "GIS_PCode"
            Case enumKey.GIS_DataFile : Return "GIS_DataFile"
            Case enumKey.GIS_DataFileRelative : Return "GIS_DataFileRelative"
            Case enumKey.GIS_DataLayer : Return "GIS_DataLayer"
            Case enumKey.GIS_DataField : Return "GIS_DataField"
            Case enumKey.GIS_DataColor0 : Return "GIS_DataColor0"
            Case enumKey.GIS_DataColor1 : Return "GIS_DataColor1"
            Case enumKey.GIS_DataColor2 : Return "GIS_DataColor2"
            Case enumKey.GIS_DataColor3 : Return "GIS_DataColor3"
            Case enumKey.GIS_DataColor4 : Return "GIS_DataColor4"
            Case enumKey.GIS_DataInvert : Return "GIS_DataInvert"
            Case enumKey.GIS_DataThresholdType : Return "GIS_DataThresholdType"
            Case enumKey.GIS_DataThresholdValue : Return "GIS_DataThresholdValue"

            Case enumKey.GISName : Return "GISName"
            Case enumKey.GISShapeFile : Return "ShapeFile"
            Case enumKey.GISShapeFileRelative : Return "ShapeFileRelative"
            Case enumKey.GISLineColor : Return "LineColor"
            Case enumKey.GISLineWidth : Return "LineWidth"
            Case enumKey.GISLineStipple : Return "LineStipple"
            Case enumKey.GISFilled : Return "Filled"
            Case enumKey.GISFillColor : Return "FillColor"
            Case enumKey.GISFillStipple : Return "Stipple"
            Case enumKey.GISFillTransparency : Return "FillTransparency"
            Case enumKey.GISVisible : Return "Visible"
            Case enumKey.GISPointColor : Return "PointColor"
            Case enumKey.GISPointSize : Return "PointSize"
            Case enumKey.GISPointType : Return "PointType"

            Case enumKey.Rpt_DateTimeRCode : Return "RptDateTimeRCode"
            Case enumKey.Rpt_DateTimeDate : Return "RptDateTimeDate"

            Case enumKey.GisQuickList : Return "GisQuickList"
            Case enumKey.GisQuickTable : Return "GisQuickTable"
            Case enumKey.GisDirectory : Return "GisDirectory"

            Case Else
                Debug.Assert(False, "Invalid key passed to SetKey")
                Return "Unknown"
        End Select
    End Function

    ''' <summary>
    ''' Set value in configuration file for general setting or currently selected project
    ''' </summary>
    ''' <param name="SectionType">Application or project setting type</param>
    ''' <param name="KeyType">Standard key type</param>
    ''' <param name="KeyText">Desired text string to set</param>
    Public Sub SetKey(ByVal SectionType As enumSection, ByVal KeyType As enumKey, ByVal KeyText As String)
        If _IniFile Is Nothing Then _IniFile = New WRDB.IniFile.clsIniFile(_IniFileName, False)
        _IniFile.SetKeyText(SectionName(SectionType), KeyName(KeyType), KeyText, "qwerty") 'setting funky default string allows blank entries to be written
    End Sub

    ''' <summary>
    ''' Set value in configuration file for non-standard section name (e.g., project other than currently selected)
    ''' </summary>
    ''' <param name="SectionName">Name of section (e.g., project name)</param>
    ''' <param name="KeyType">Standard key type</param>
    ''' <param name="KeyText">Desired text string to set</param>
    Public Sub SetKey(ByVal SectionName As String, ByVal KeyType As enumKey, ByVal KeyText As String)
        If _IniFile Is Nothing Then _IniFile = New WRDB.IniFile.clsIniFile(_IniFileName, False)
        _IniFile.SetKeyText(SectionName, KeyName(KeyType), KeyText, "qwerty")
    End Sub

    ''' <summary>
    ''' Set value in configuration file for non-standard key name (e.g., those that are not enumerated above)
    ''' </summary>
    ''' <param name="SectionType">Type of section (e.g., ExternalConnection)</param>
    ''' <param name="KeyName">Key name (e.g., name of connection)</param>
    ''' <param name="KeyText">Desired text string to set</param>
    Public Sub SetKey(ByVal SectionType As enumSection, ByVal KeyName As String, ByVal KeyText As String)
        If _IniFile Is Nothing Then _IniFile = New WRDB.IniFile.clsIniFile(_IniFileName, False)
        _IniFile.SetKeyText(SectionName(SectionType), KeyName, KeyText, "qwerty")
    End Sub

    ''' <summary>
    ''' Retrieve setting from configuration file for general setting or currently selected project
    ''' </summary>
    ''' <param name="SectionType">Application or project setting type</param>
    ''' <param name="KeyType">Standard key type</param>
    ''' <param name="DefaultKeyText">If section/key not found, returns this value</param>
    ''' <returns></returns>
    Public Function GetKey(ByVal SectionType As enumSection, ByVal KeyType As enumKey, Optional ByVal DefaultKeyText As String = "") As String
        If _IniFile Is Nothing Then _IniFile = New WRDB.IniFile.clsIniFile(_IniFileName, False)
        Dim KeyText As String = _IniFile.GetKeyText(SectionName(SectionType), KeyName(KeyType))
        If KeyText = "" Then KeyText = DefaultKeyText
        Return KeyText
    End Function

    ''' <summary>
    ''' Retrieve non-project setting from configuration file for project other than one currently selected
    ''' </summary>
    ''' <param name="SectionName">Name of section (project)</param>
    ''' <param name="KeyType">Standard key type</param>
    ''' <param name="DefaultKeyText">If section/key not found, returns this value</param>
    ''' <returns></returns>
    Public Function GetKey(ByVal SectionName As String, ByVal KeyType As enumKey, Optional ByVal DefaultKeyText As String = "") As String
        If _IniFile Is Nothing Then _IniFile = New WRDB.IniFile.clsIniFile(_IniFileName, False)
        Dim KeyText As String = _IniFile.GetKeyText(SectionName, KeyName(KeyType))
        If KeyText = "" Then KeyText = DefaultKeyText
        Return KeyText
    End Function

    ''' <summary>
    ''' Set value in configuration file for non-standard key name (e.g., those that are not enumerated above)
    ''' </summary>
    ''' <param name="SectionType">Type of section (e.g., ExternalConnection)</param>
    ''' <param name="KeyName">Key name (e.g., name of connection)</param>
    ''' <param name="DefaultKeyText">If section/key not found, returns this value</param>
    Public Function GetKey(ByVal SectionType As enumSection, ByVal KeyName As String, Optional ByVal DefaultKeyText As String = "") As String
        If _IniFile Is Nothing Then _IniFile = New WRDB.IniFile.clsIniFile(_IniFileName, False)
        Dim KeyText As String = _IniFile.GetKeyText(SectionName(SectionType), KeyName)
        If KeyText = "" Then KeyText = DefaultKeyText
        Return KeyText
    End Function

    Public Function DeleteProject(ByVal ProjectName As String) As Boolean
        If _IniFile Is Nothing Then _IniFile = New WRDB.IniFile.clsIniFile(_IniFileName, False)
        Dim success As Boolean = _IniFile.DeleteSection(ProjectName)
        Return success
    End Function

    Public Function RenameProject(ByVal OldName As String, ByVal NewName As String) As Boolean
        If _IniFile Is Nothing Then _IniFile = New WRDB.IniFile.clsIniFile(_IniFileName, False)
        Dim success As Boolean = _IniFile.RenameSection(OldName, NewName)
        Return success
    End Function

    Public Function DeleteKey(ByVal SectionType As enumSection, ByVal KeyName As String) As Boolean
        If _IniFile Is Nothing Then _IniFile = New WRDB.IniFile.clsIniFile(_IniFileName, False)
        Dim success As Boolean = _IniFile.DeleteKey(KeyName, SectionName(SectionType))
        Return success
    End Function

    ''' <summary>
    ''' Each section in the ini file is a project name (except Settings and DatabaseConnections, which holds WRDB settings for all projects)
    ''' </summary>
    ''' <returns></returns>
    Public Function GetProjectNames() As Collections.ArrayList
        If _IniFile Is Nothing Then _IniFile = New WRDB.IniFile.clsIniFile(_IniFileName, False)
        Dim al As ArrayList = _IniFile.GetSectionNames
        al.Remove(SectionName(enumSection.Application))
        al.Remove(SectionName(enumSection.ExternalConnection))
        If al.Contains(SectionName(enumSection.ExternalConnection)) Then al.Remove(SectionName(enumSection.ExternalConnection))
        If al.Contains("") Then al.Remove("")
        If al.Contains(" ") Then al.Remove(" ")
        Return al
    End Function

    ''' <summary>
    ''' Sets the name of the project which defines the name of the section used to store project-specific information
    ''' </summary>
    ''' <param name="ProjectName">Name of project</param>
    Public Sub SetProjectName(ByVal ProjectName As String)
        _ProjectName = ProjectName
    End Sub

    Public Function ErrorText(ByVal ex As Exception) As String
        Return String.Format("A file error occurred while trying to update the WRDB settings file: \n\n{0}\n\nThe detailed error message was:\n\n{1}".Replace("\n", vbCr), FileName, ex.Message)
    End Function

#Region "External Connection and Table Mapping..."

    ''' <summary>
    ''' Database connections contain information to allow WRDB and Graph to save info for external database connections
    ''' </summary>
    Public Function GetConnectionNames() As Collections.ArrayList
        If _IniFile Is Nothing Then _IniFile = New WRDB.IniFile.clsIniFile(_IniFileName, False)
        Dim lst As New ArrayList
        For Each s As String In _IniFile.GetKeyNames(SectionName(enumSection.ExternalConnection))
            If Not s.Contains(":") Then lst.Add(s)
        Next
        Return lst
    End Function

    Public Property ConnectionInfo(ByVal ConnectionName As String) As clsConnection
        Get
            If _IniFile Is Nothing Then _IniFile = New WRDB.IniFile.clsIniFile(_IniFileName, False)
            Dim ConnectInfo As String = _IniFile.GetKeyText(SectionName(enumSection.ExternalConnection), ConnectionName)
            Dim ar() As String = ConnectInfo.Split(vbTab)
            Dim Connection As New clsConnection(ConnectionName)
            With Connection
                For i As Integer = 0 To ar.Length - 1
                    Select Case i
                        Case 0 : .DatabaseType = [Enum].Parse(GetType(clsDB.enumDBType), ar(i))
                        Case 1 : .ServerAddress = ar(i)
                        Case 2 : .DatabaseName = ar(i)
                        Case 3 : .UserName = ar(i)
                        Case 4 : .Password = DecryptText(ar(i))
                    End Select
                Next
                Return Connection
            End With
        End Get
        Set(ByVal Connection As clsConnection)
            With Connection
                Dim ConnectInfo As String = String.Format("{0}\t{1}\t{2}\t{3}\t{4}", .DatabaseType.ToString, .ServerAddress, .DatabaseName, .UserName, EncryptText(.Password)).Replace("\t", vbTab)
                _IniFile.SetKeyText(SectionName(enumSection.ExternalConnection), ConnectionName, ConnectInfo)
            End With
            _IniFile.Save()
        End Set
    End Property

    ' ''' <summary>
    ' ''' Set external database connection information
    ' ''' Connection information is saved in a single entry, tab-delimited
    ' ''' </summary>
    ' ''' <param name="ConnectionName">Name of connection</param>
    ' ''' <param name="DatabaseType">Data provider type</param>
    ' ''' <param name="ServerAddress">URL of database server</param>
    ' ''' <param name="DatabaseName">Name of database</param>
    ' ''' <param name="UserName">Username (doesn't handle NT authentication)</param>
    ' ''' <param name="Password">Password</param>
    'Public Sub SetConnectionInfo(ByVal ConnectionName As String, ByVal DatabaseType As String, ByVal ServerAddress As String, ByVal DatabaseName As String, ByVal UserName As String, ByVal Password As String)
    '    Dim ConnectInfo As String = String.Format("{0}\t{1}\t{2}\t{3}\t{4}", DatabaseType, ServerAddress, DatabaseName, UserName, Password).Replace("\t", vbTab)
    '    _IniFile.SetKeyText(SectionName(enumSection.ExternalConnection), ConnectionName, ConnectInfo)
    'End Sub

    ' ''' <summary>
    ' ''' Get external database connection information
    ' ''' Connection information is saved in a single entry, tab-delimited
    ' ''' </summary>
    ' ''' <param name="ConnectionName">Name of connection</param>
    ' ''' <param name="DatabaseType">Data provider type</param>
    ' ''' <param name="ServerAddress">URL of database server</param>
    ' ''' <param name="DatabaseName">Name of database</param>
    ' ''' <param name="UserName">Username (doesn't handle NT authentication)</param>
    ' ''' <param name="Password">Password</param>
    'Public Sub GetConnectionInfo(ByVal ConnectionName As String, ByRef DatabaseType As String, ByRef ServerAddress As String, ByRef DatabaseName As String, ByRef UserName As String, ByRef Password As String)
    '    If _IniFile Is Nothing Then _IniFile = New WRDB.IniFile.clsIniFile(_IniFileName, False)
    '    Dim ConnectInfo As String = _IniFile.GetKeyText(SectionName(enumSection.ExternalConnection), ConnectionName)
    '    Dim ar() As String = ConnectInfo.Split(vbTab)
    '    For i As Integer = 0 To ar.Length - 1
    '        Select Case i
    '            Case 0 : DatabaseType = ar(i)
    '            Case 1 : ServerAddress = ar(i)
    '            Case 2 : DatabaseName = ar(i)
    '            Case 3 : UserName = ar(i)
    '            Case 4 : Password = ar(i)
    '        End Select
    '    Next
    'End Sub

    ''' <summary>
    ''' Database connection mapping contain information about mapping of WRDB data fields for a specific table, selected stations, and selected parameters
    ''' Key is CONNECTIONNAME:TABLECONNECTIONNAME
    ''' Value is TABLENAME:FIELDNAMES:STATIONLIST:STATIONS:PARAMETERLIST:PARAMETERS (each are tab-delimited):MINDATE:MAXDATE
    ''' </summary>
    Public Function GetMappingTables(ByVal ConnectionName As String) As Collections.ArrayList
        If _IniFile Is Nothing Then _IniFile = New WRDB.IniFile.clsIniFile(_IniFileName, False)
        Dim lst As New ArrayList
        For Each s As String In _IniFile.GetKeyNames(SectionName(enumSection.ExternalConnection))
            If s.Contains(":") AndAlso s.Split(":")(0) = ConnectionName Then lst.Add(s.Split(":")(1))
        Next
        Return lst
    End Function

    Public Property TableMappingInfo(ByVal ConnectionName As String, ByVal TableConnectionName As String) As clsTableMapping
        Get
            If _IniFile Is Nothing Then _IniFile = New WRDB.IniFile.clsIniFile(_IniFileName, False)
            Dim MappingInfo As String = _IniFile.GetKeyText(SectionName(enumSection.ExternalConnection), ConnectionName & ":" & TableConnectionName)
            Dim ar() As String = MappingInfo.Split(":")
            Dim TableMapping As New clsTableMapping(TableConnectionName)
            With TableMapping
                .TableName = ar(0)
                If ar.Length >= 2 Then .alFieldNames.AddRange(ar(1).Split(vbTab))
                If ar.Length >= 3 AndAlso ar(2) <> "" Then .alAvailStations.AddRange(ar(2).Split(vbTab))
                If ar.Length >= 4 AndAlso ar(3) <> "" Then .alSelectedStations.AddRange(ar(3).Split(vbTab))
                If ar.Length >= 5 AndAlso ar(4) <> "" Then .alAvailParameters.AddRange(ar(4).Split(vbTab))
                If ar.Length >= 6 AndAlso ar(5) <> "" Then .alSelectedParameters.AddRange(ar(5).Split(vbTab))
                If ar.Length >= 7 AndAlso IsDate(ar(6)) Then .MinDate = ar(6) Else .MinDate = Date.MinValue
                If ar.Length >= 8 AndAlso IsDate(ar(7)) Then .MaxDate = ar(7) Else .MaxDate = Date.MaxValue
                If ar.Length >= 9 Then .BypassMapping = CBool(ar(8)) Else .BypassMapping = False
            End With
            Return TableMapping
        End Get
        Set(ByVal TableMapping As clsTableMapping)
            If _IniFile Is Nothing Then _IniFile = New WRDB.IniFile.clsIniFile(_IniFileName, False)
            With TableMapping
                Dim MappingInfo As String = ""
                For Each s As String In .alFieldNames
                    MappingInfo &= IIf(MappingInfo = "", "", vbTab) & s
                Next
                Dim StaList As String = ""
                If .alAvailStations IsNot Nothing Then
                    For Each s As String In .alAvailStations
                        StaList &= IIf(StaList = "", "", vbTab) & s
                    Next
                End If
                Dim Stations As String = ""
                If .alSelectedStations IsNot Nothing Then
                    For Each s As String In .alSelectedStations
                        Stations &= IIf(Stations = "", "", vbTab) & s
                    Next
                End If
                Dim Parms As String = ""
                If .alSelectedParameters IsNot Nothing Then
                    For Each s As String In .alSelectedParameters
                        Parms &= IIf(Parms = "", "", vbTab) & s
                    Next
                End If
                Dim ParmList As String = ""
                If .alAvailParameters IsNot Nothing Then
                    For Each s As String In .alAvailParameters
                        ParmList &= IIf(ParmList = "", "", vbTab) & s
                    Next
                End If
                _IniFile.SetKeyText(SectionName(enumSection.ExternalConnection), ConnectionName & ":" & TableConnectionName,
                                    .TableName & ":" & MappingInfo & ":" &
                                    StaList & ":" & Stations & ":" &
                                    ParmList & ":" & Parms & ":" &
                                    .MinDate.Date.ToString("MM/dd/yyyy") & ":" & .MaxDate.Date.ToString("MM/dd/yyyy") & ":" & .BypassMapping)
                _IniFile.Save()
            End With
        End Set
    End Property

    ' ''' <summary>
    ' ''' Set external database mapping for each field
    ' ''' Connection mapping information for table is saved in a single entry, colon- and tab-delimited
    ' ''' </summary>
    ' ''' <param name="ConnectionName">Name of connection</param>
    ' ''' <param name="TableConnectionName">Name of table connection</param>
    ' ''' <param name="TableName">Name of table</param>
    ' ''' <param name="FieldNames">Array of external field names mapped to the following: Station_ID, PCode, Date_Time, Result, RCode, CCode, Agency, LEW_Pct, Depth_M</param>
    ' ''' <param name="AvailStations">Array of all available stations in source table (cached)</param>
    ' ''' <param name="SelectedStations">Array of Station IDs to be imported (will be empty if all are desired)</param>
    ' ''' <param name="AvailPCodes">Array of PCodes to be imported (will be empty if all are desired)</param>
    ' ''' <param name="SelectedPCodes">Array of all availabel parameters in source table (cached)</param>
    ' ''' <param name="MinDate">Minimum date in range to be imported</param>
    ' ''' <param name="MaxDate">Maximum date in range to be imported</param>
    'Public Sub SetMappingInfo(ByVal ConnectionName As String, ByVal TableConnectionName As String, ByVal TableName As String,
    '                          ByVal BypassMapping As Boolean, ByVal FieldNames As ArrayList,
    '                          ByVal AvailStations As ArrayList, ByVal SelectedStations As ArrayList,
    '                          ByVal AvailPCodes As ArrayList, ByVal SelectedPCodes As ArrayList,
    '                          ByVal MinDate As Date, ByVal MaxDate As Date)
    '    Dim MappingInfo As String = ""
    '    For Each s As String In FieldNames
    '        MappingInfo &= IIf(MappingInfo = "", "", vbTab) & s
    '    Next
    '    Dim StaList As String = ""
    '    If AvailStations IsNot Nothing Then
    '        For Each s As String In AvailStations
    '            StaList &= IIf(StaList = "", "", vbTab) & s
    '        Next
    '    End If
    '    Dim Stations As String = ""
    '    If SelectedStations IsNot Nothing Then
    '        For Each s As String In SelectedStations
    '            Stations &= IIf(Stations = "", "", vbTab) & s
    '        Next
    '    End If
    '    Dim Parms As String = ""
    '    If SelectedPCodes IsNot Nothing Then
    '        For Each s As String In SelectedPCodes
    '            Parms &= IIf(Parms = "", "", vbTab) & s
    '        Next
    '    End If
    '    Dim ParmList As String = ""
    '    If AvailPCodes IsNot Nothing Then
    '        For Each s As String In AvailPCodes
    '            ParmList &= IIf(ParmList = "", "", vbTab) & s
    '        Next
    '    End If
    '    _IniFile.SetKeyText(SectionName(enumSection.ExternalConnection), ConnectionName & ":" & TableConnectionName,
    '                        TableName & ":" & MappingInfo & ":" &
    '                        StaList & ":" & Stations & ":" &
    '                        ParmList & ":" & Parms & ":" &
    '                        MinDate.Date & ":" & MaxDate.Date & ":" & BypassMapping)
    'End Sub

    ' ''' <summary>
    ' ''' Get external database mapping for each field
    ' ''' Connection mapping information for table is saved in a single entry, colon- and tab-delimited
    ' ''' </summary>
    ' ''' <param name="ConnectionName">Name of connection</param>
    ' ''' <param name="TableConnectionName">Name of table connection</param>
    ' ''' <param name="TableName">Name of table</param>
    ' ''' <param name="BypassMapping">If true, field mapping will not be used and table will be treated as native WRDB table</param>
    ' ''' <param name="FieldNames">Array of external field names mapped to the following: Station_ID, PCode, Date_Time, Result, RCode, CCode, Agency, LEW_Pct, Depth_M</param>
    ' ''' <param name="AvailStations">Array of all available stations in source table (cached)</param>
    ' ''' <param name="SelectedStations">Array of Station IDs to be imported (will be empty if all are desired)</param>
    ' ''' <param name="AvailPCodes">Array of all availabel parameters in source table (cached)</param>
    ' ''' <param name="SelectedPCodes">Array of PCodes to be imported (will be empty if all are desired)</param>
    ' ''' <param name="MinDate">Minimum date in range to be imported</param>
    ' ''' <param name="MaxDate">Maximum date in range to be imported</param>
    'Public Sub GetMappingInfo(ByVal ConnectionName As String, ByVal TableConnectionName As String, ByRef TableName As String,
    '                          ByRef BypassMapping As Boolean, ByRef FieldNames As ArrayList,
    '                          ByRef AvailStations As ArrayList, ByRef SelectedStations As ArrayList,
    '                          ByRef AvailPCodes As ArrayList, ByRef SelectedPCodes As ArrayList,
    '                          ByRef MinDate As Date, ByRef MaxDate As Date)
    '    FieldNames = New ArrayList
    '    AvailStations = New ArrayList
    '    SelectedStations = New ArrayList
    '    AvailPCodes = New ArrayList
    '    SelectedPCodes = New ArrayList
    '    Dim MappingInfo As String = _IniFile.GetKeyText(SectionName(enumSection.ExternalConnection), ConnectionName & ":" & TableConnectionName)
    '    Dim ar() As String = MappingInfo.Split(":")
    '    TableName = ar(0)
    '    If ar.Length >= 2 Then FieldNames.AddRange(ar(1).Split(vbTab))
    '    If ar.Length >= 3 AndAlso ar(2) <> "" Then AvailStations.AddRange(ar(2).Split(vbTab))
    '    If ar.Length >= 4 AndAlso ar(3) <> "" Then SelectedStations.AddRange(ar(3).Split(vbTab))
    '    If ar.Length >= 5 AndAlso ar(4) <> "" Then AvailPCodes.AddRange(ar(4).Split(vbTab))
    '    If ar.Length >= 6 AndAlso ar(5) <> "" Then SelectedPCodes.AddRange(ar(5).Split(vbTab))
    '    If ar.Length >= 7 AndAlso IsDate(ar(6)) Then MinDate = ar(6) Else MinDate = Date.MinValue
    '    If ar.Length >= 8 AndAlso IsDate(ar(7)) Then MaxDate = ar(7) Else MaxDate = Date.MaxValue
    '    If ar.Length >= 9 Then BypassMapping = CBool(ar(8)) Else BypassMapping = False
    'End Sub

    ' ''' <summary>
    ' ''' Get external database mapping for each field
    ' ''' Connection mapping information for table is saved in a single entry, colon- and tab-delimited
    ' ''' </summary>
    ' ''' <param name="ConnectionName">Name of connection</param>
    ' ''' <param name="TableConnectionName">Name of table connection</param>
    ' ''' <param name="TableName">Name of table</param>
    ' ''' <param name="BypassMapping">If true, field mapping will not be used and table will be treated as native WRDB table</param>
    'Public Sub GetMappingInfo(ByVal ConnectionName As String, ByVal TableConnectionName As String, ByRef TableName As String,
    '                          ByRef BypassMapping As Boolean)
    '    Dim MappingInfo As String = _IniFile.GetKeyText(SectionName(enumSection.ExternalConnection), ConnectionName & ":" & TableConnectionName)
    '    Dim ar() As String = MappingInfo.Split(":")
    '    TableName = ar(0)
    '    If ar.Length >= 9 Then BypassMapping = CBool(ar(8)) Else BypassMapping = False
    'End Sub

    ' ''' <summary>
    ' ''' Get external database mapping for each field
    ' ''' Connection mapping information for table is saved in a single entry, colon- and tab-delimited
    ' ''' </summary>
    ' ''' <param name="ConnectionName">Name of connection</param>
    ' ''' <param name="TableConnectionName">Name of table connection</param>
    ' ''' <param name="TableName">Name of table</param>
    'Public Sub GetMappingInfo(ByVal ConnectionName As String, ByVal TableConnectionName As String, ByRef TableName As String)
    '    Dim MappingInfo As String = _IniFile.GetKeyText(SectionName(enumSection.ExternalConnection), ConnectionName & ":" & TableConnectionName)
    '    Dim ar() As String = MappingInfo.Split(":")
    '    TableName = ar(0)
    'End Sub
#End Region

    Public Sub Save()
        If _IniFile IsNot Nothing Then
            _IniFile.Sort()
            _IniFile.Save()
        End If
    End Sub

    ''' <summary>
    ''' This will force the inifile to be reopened the next time a value is read
    ''' </summary>
    Public Sub Reopen()
        _IniFile = Nothing
    End Sub

    ''' <summary>
    ''' Open existing WRDB.ini file in directory previously specified (and stored in registry); by default goes into MyDocuments\WRDB
    ''' </summary>
    ''' <remarks>Error will occur if file does not already exist</remarks>
    Public Sub New()
        Dim AppDataPath As String = GetSetting(REGAPP, "General", "AppDataPath", My.Computer.FileSystem.SpecialDirectories.MyDocuments & "\WRDB")
        _IniFileName = AppDataPath & "\WRDB.INI"
    End Sub

    ''' <summary>
    ''' Open existing configuration file
    ''' </summary>
    ''' <param name="FileName">Name of existing .ini file to open (full path); if is empty, will open WRDB.ini file in previously saved directory</param>
    ''' <remarks></remarks>
    Public Sub New(ByRef FileName As String)
        If FileName = "" Then
            Dim AppDataPath As String = GetSetting(REGAPP, "General", "AppDataPath", My.Computer.FileSystem.SpecialDirectories.MyDocuments & "\WRDB")
            FileName = AppDataPath & "\WRDB.INI"
            _IniFileName = FileName
        Else
            _IniFileName = FileName
        End If
    End Sub

    ''' <summary>
    ''' See if ini file exists and is not locked
    ''' </summary>
    <DebuggerStepThrough()>
    Public Function Exists() As Boolean
        Try
            If My.Computer.FileSystem.FileExists(_IniFileName) Then
                'check for locked here because it will react as if it doesn't exist but really want an error message
                Dim sr As New System.IO.StreamReader(FileName)
                sr.Dispose()
                Return True
            End If
        Catch ex As IO.IOException
            Throw
            Return True 'don't want it to act like file needs to be created
        End Try
    End Function

    ''' <summary>
    ''' Create new (or overwrite existing) INI file
    ''' </summary>
    Public Sub Create()
        _IniFile = New IniFile.clsIniFile(_IniFileName, True)
    End Sub
End Class

Public Class clsConnection
    Public Property ConnectionName As String = ""
    Public Property DatabaseType As clsDB.enumDBType = clsDB.enumDBType.SQL_Server
    Public Property ServerAddress As String = ""
    Public Property DatabaseName As String = ""
    Public Property UserName As String = ""
    Public Property Password As String = ""

    Sub New(ByVal _ConnectionName As String)
        ConnectionName = _ConnectionName
    End Sub

    ''' <summary>
    ''' Set external database connection information
    ''' Connection information is saved in a single entry, tab-delimited
    ''' </summary>
    ''' <param name="_ConnectionName">Name of connection</param>
    ''' <param name="_DatabaseType">Data provider type</param>
    ''' <param name="_ServerAddress">URL of database server</param>
    ''' <param name="_DatabaseName">Name of database</param>
    ''' <param name="_UserName">Username (doesn't handle NT authentication)</param>
    ''' <param name="_Password">Password</param>
    Sub New(ByVal _ConnectionName As String, ByVal _DatabaseType As clsDB.enumDBType, ByVal _ServerAddress As String, ByVal _DatabaseName As String, ByVal _UserName As String, ByVal _Password As String)
        ConnectionName = _ConnectionName
        DatabaseType = _DatabaseType
        ServerAddress = _ServerAddress
        DatabaseName = _DatabaseName
        UserName = _UserName
        Password = _Password
    End Sub
End Class

''' <summary>
''' Store external table connection info
''' </summary>
Public Class clsTableMapping

    Public Property TableConnectionName As String = ""
    Public Property TableName As String = ""
    Public Property BypassMapping As Boolean = False
    Public Property alFieldNames As New ArrayList
    Public Property alAvailStations As New ArrayList
    Public Property alSelectedStations As New ArrayList
    Public Property alAvailParameters As New ArrayList
    Public Property alSelectedParameters As New ArrayList
    Public Property MinDate As Date = Date.MinValue
    Public Property MaxDate As Date = Date.MaxValue

    Sub New(ByVal _TableMappingName As String)
        TableConnectionName = _TableMappingName
    End Sub

    ''' <summary>
    ''' Set external database mapping for each field
    ''' Connection mapping information for table is saved in a single entry, colon- and tab-delimited
    ''' </summary>
    ''' <param name="_TableConnectionName">Name of table connection</param>
    ''' <param name="_TableName">Name of table</param>
    ''' <param name="_BypassMapping">If true, will bypass all field mapping and treat as native WRDB table</param>
    ''' <param name="_alFieldNames">Array of external field names mapped to the following: Station_ID, PCode, Date_Time, Result, RCode, CCode, Agency, LEW_Pct, Depth_M</param>
    ''' <param name="_alAvailStations">Array of all available stations in source table (cached)</param>
    ''' <param name="_alSelectedStations">Array of Station IDs to be imported (will be empty if all are desired)</param>
    ''' <param name="_alAvailParameters">Array of PCodes to be imported (will be empty if all are desired)</param>
    ''' <param name="_alSelectedParameters ">Array of all availabel parameters in source table (cached)</param>
    ''' <param name="_MinDate">Minimum date in range to be imported</param>
    ''' <param name="_MaxDate">Maximum date in range to be imported</param>
    Sub New(ByVal _TableConnectionName As String, ByVal _TableName As String, ByVal _BypassMapping As Boolean, ByVal _alFieldNames As ArrayList,
            ByVal _alAvailStations As ArrayList, ByVal _alSelectedStations As ArrayList,
            ByVal _alAvailParameters As ArrayList, ByVal _alSelectedParameters As ArrayList,
            ByVal _MinDate As Date, ByVal _MaxDate As Date)
        TableConnectionName = _TableConnectionName
        TableName = _TableName
        BypassMapping = _BypassMapping
        alFieldNames = _alFieldNames
        alAvailStations = _alAvailStations
        alSelectedStations = _alSelectedStations
        alAvailParameters = _alAvailParameters
        alSelectedParameters = _alSelectedParameters
        MinDate = _MinDate
        MaxDate = _MaxDate
    End Sub
End Class
